import { SorterResult } from 'antd/lib/table/interface';
import moment from 'moment';
import { OrderInfo } from '@inbiz/hooks/useModelList';
import { ConditionsType, RecordType } from './interfaces';
import {
  arrIsEmpty,
  ConnectorEnum,
  OperatorEnum,
} from './shared';


/**
 * 获取模型
 * @param queryFields 查询器配置字段
 */
const getModels = (queryFields?: any[]) => {
  if (arrIsEmpty(queryFields) || !queryFields) {
    return {};
  }
  return queryFields.reduce((modal, next) => {
    modal[next.value] = next;
    return modal;
  }, {});
};

/**
 * 获取模型名字
 * @param fieldName 字段名
 * @param models 模型
 */
const getModelName = (fieldName: string, models: any): string[] => {
  if (!models[fieldName]) {
    return ['', fieldName];
  }
  return models[fieldName].origin_FieldName.split('$');
};

/**
 * 格式化排序参数
 * @param orders 排序参数
 * @param sorter 表格排序字段
 * @param models 模型
 */
const formatOrders = (
  orders: OrderInfo[],
  sorter: SorterResult<RecordType>,
  models: any,
): OrderInfo[] => {
  const oldOrder = orders.find((item) => item.fieldName === sorter.field);
  if (!oldOrder) {
    if (sorter.column) {
      const [modelName, fieldName] = getModelName(sorter.field as string, models);
      const order: OrderInfo = {
        modelName,
        fieldName,
        sortType: sorter.order === 'ascend' ? 'asc' : 'desc',
        order: orders.length,
      };
      return [...orders, order];
    }
  } else {
    const filter = orders.filter((item) => item.fieldName !== sorter.field);
    if (sorter.column) {
      const order: OrderInfo = {
        ...oldOrder,
        sortType: sorter.order === 'ascend' ? 'asc' : 'desc',
      };
      return [...filter, order];
    } else {
      return filter;
    }
  }
  return [];
};

/**
 * 格式化查询参数
 * @param field 字段
 * @param _condition 查询条件
 * @param conditionInfo 查询条件的相关字段
 * @param queryGroup 查询条件
 */
const formatValue = (
  field: { value: any; type: string },
  _condition: {
    index: number;
    connector: ConnectorEnum;
    condition: any[];
  },
  conditionInfo: {
    connector?: ConnectorEnum;
    field?: string;
    modelName?: any;
    operator: any;
    value?: any;
    name?: string;
  },
  queryGroup: { index?: number; connector?: ConnectorEnum; condition: any }[],
) => {
  const { value, type } = field || {};
  if (value == null || value === '') {
    return;
  }
  switch (type) {
    case 'EformDateRangePicker': {
      const [start, end] = Array.isArray(value) ? value : [];
      if (!start) {
        return;
      }
      conditionInfo.operator = OperatorEnum.gte;
      conditionInfo.value = moment(start).format('YYYY-MM-DD HH:mm:ss');
      _condition.condition.push(conditionInfo);
      const endQuery = { ...conditionInfo };
      endQuery.operator = OperatorEnum.lte;
      endQuery.value = moment(end).format('YYYY-MM-DD HH:mm:ss');
      _condition.condition.push(endQuery);
      return queryGroup.push(_condition);
    }
    case 'EformDatePicker': {
      conditionInfo.value = moment(value).format('YYYY-MM-DD');
      return queryGroup.push({
        index: 0,
        connector: ConnectorEnum.and,
        condition: [{ ...conditionInfo }],
      });
    }
    case 'EformNumber': {
      conditionInfo.operator = OperatorEnum.eq;
      conditionInfo.value = value;
      return queryGroup.push({
        index: 0,
        connector: ConnectorEnum.and,
        condition: [{ ...conditionInfo }],
      });
    }
    case 'EformSwitch': {
      conditionInfo.operator = OperatorEnum.eq;
      conditionInfo.value = value;
      return queryGroup.push({
        index: 0,
        connector: ConnectorEnum.and,
        condition: [{ ...conditionInfo }],
      });
    }
    case 'EformMemberSelect': {
      if (Array.isArray(value)) {
        value?.forEach((item) => {
          _condition.condition.push({
            ...conditionInfo,
            value: item.Id,
            operator: OperatorEnum.like,
            connector: value.length == 1 ? ConnectorEnum.and : ConnectorEnum.or,
          });
        });
      } else {
        conditionInfo.value = value;
        _condition.condition.push(conditionInfo);
      }
      if (_condition.condition.length) {
        queryGroup.push(_condition);
      }
      return;
    }
    case 'EformDynamicList': {
      if (Array.isArray(value)) {
        value?.forEach((item) => {
          _condition.condition.push({
            ...conditionInfo,
            value: item,
            operator: OperatorEnum.like,
            connector: value.length == 1 ? ConnectorEnum.and : ConnectorEnum.or,
          });
        });
      } else {
        conditionInfo.value = value;
        _condition.condition.push(conditionInfo);
      }
      if (_condition.condition.length) {
        queryGroup.push(_condition);
      }
      return;
    }
    case 'Cascader': {
      if (Array.isArray(value)) {
        value?.forEach((item) => {
          _condition.condition.push({
            ...conditionInfo,
            value: item.toString(),
            operator: OperatorEnum.likein,
            connector: value.length == 1 ? ConnectorEnum.and : ConnectorEnum.or,
          });
        });
      } else {
        conditionInfo.value = value.toString();
        _condition.condition.push(conditionInfo);
      }
      if (_condition.condition.length) {
        queryGroup.push(_condition);
      }
      return;
    }
    case 'TreeSelect': {
      if (Array.isArray(value)) {
        value?.forEach((item) => {
          _condition.condition.push({
            ...conditionInfo,
            value: Array.isArray(item) ? item[item.length - 1] : item,
            operator: OperatorEnum.likein,
            connector: value.length == 1 ? ConnectorEnum.and : ConnectorEnum.or,
          });
        });
      } else {
        conditionInfo.value = value;
        _condition.condition.push(conditionInfo);
      }
      if (_condition.condition.length) {
        queryGroup.push(_condition);
      }
      return;
    }
    case 'EformStaticList': {
      if (Array.isArray(value)) {
        value?.forEach((item) => {
          _condition.condition.push({
            ...conditionInfo,
            value: item,
            operator: OperatorEnum.like,
            connector: value.length == 1 ? ConnectorEnum.and : ConnectorEnum.or,
          });
        });
      } else {
        conditionInfo.value = value;
        _condition.condition.push(conditionInfo);
      }
      if (_condition.condition.length) {
        queryGroup.push(_condition);
      }
      return;
    }
    default: {
      conditionInfo.value = value;
      return queryGroup.push({
        index: 0,
        connector: ConnectorEnum.and,
        condition: [{ ...conditionInfo }],
      });
    }
  }
};

/**
 * 过滤查询条件，剔除查询值不存在和删除字符串前后空格
 * @param conditions 查询条件
 * @returns 过滤后的条件
 */
// 模型内置字段，用成员选择控件查询时，不需要带类型
const memberKey = ['creatorid', 'department', 'lastmodifierid'] 
const filterCondition = (conditions: any) => {
  let cache: any = [];
  if (conditions && conditions.length > 0) {
    conditions.forEach(({ condition, ...other }: any) => {
      let group = { ...other, condition: [] } as any;
      if (condition?.length) {
        condition.forEach(({ value, field, ...item }: any) => {
          let cacheValue = typeof value === 'string' ? value.trim() : value;
          if (cacheValue != null && cacheValue !== '') {
            if (memberKey.includes(field) && cacheValue?.indexOf?.(':') === 1) {
              cacheValue = cacheValue.slice(2)
            }
            let modelName, fieldName;
            if (field && field?.indexOf('$') != -1) {
              [modelName, fieldName] = field.split('$');
            } else {
              fieldName = field;
              modelName = '';
            }
            group.condition.push({
              value: cacheValue,
              field: fieldName,
              modelName,
              ...item,
            });
          }
        });
      } else {
        if (other?.value && other.value !== '')
          cache.push({
            condition: [other],
            connector: 'and',
            index: 0,
          });
      }
      if (group.condition.length) {
        cache.push(group);
      }
    });
  }
  return cache;
};

const formatFilterCondition = (type: string, originData) => {
  if (type === 'api') {
    return originData.map((ele) => {
      const { condition = [] } = ele;
      return {
        ...ele,
        condition: condition.map((child) => ({ ...child, field: child.name, name: null })),
      };
    });
  }
  return originData;
};

/**
 * 组装查询参数
 * @param queryFields 查询器配置字段
 * @param values 查询框表单值
 */
const getQueryGroups = (
  queryFields: any[],
  values: { [x: string]: any },
  initParams?: any[],
): ConditionsType[] => {
  const models = getModels(queryFields);
  let conditions: { index: number; connector: ConnectorEnum; condition: [] }[] = [];
  Object.keys(values).forEach((field) => {
    const [modelName, fieldName] = getModelName(field, models);
    let _condition = {
      index: 0,
      connector: ConnectorEnum.and,
      condition: [],
    };
    let conditionInfo = {
      connector: ConnectorEnum.and,
      field: fieldName,
      modelName,
      operator: OperatorEnum.like,
      name: values[field].name,
    };
    formatValue(values[field], _condition, conditionInfo, conditions);
  });
  if (initParams && initParams.length > 0) {
    initParams.forEach((param) => conditions.push(param));
  }
  return conditions;
};

// 格式化成员选择的数据
const formatMemberSelectValue = (
  value: { [x: string]: any; key: string; Id: string },
  tabs: {[key: string]: any}[],
) => {
  const [type] = value.key.split('-');
  const isMulti = tabs.filter(tab => !tab?.hide)?.length > 1;
  const MemberTypeKeyMap = {
    user: 0,
    group: 3,
    position: 4,
    department: 5,
  };
  // 单个tab只保值存id
  // 多个tab 保存 type:id
  if (isMulti) {
    return {
      Id: `${MemberTypeKeyMap[type]}:${value.id}`,
    };
  }
  return {
    Id: value.id,
  };
};

/**
 * 过滤html标签
 */
const removeHtmlTag = (str: string) => {
  if (!str && Number(str) != 0) return '';
  try {
    str = str
      .replace(/<\/?[^>]*>/g, '')
      .replace(/[ | ]*\n/g, '\n')
      .replace(/\n[\s| | ]*\r/g, '\n')
      .replace(/&nbsp;/gi, '')
      .replace(/\r\n/gi, '')
      .replace(/\n/gi, '');
    return str;
  } catch (ex) {
    return str;
  }
};
const formatConditionValue = (field) => {
  switch (field.componentType) {
    case 'EformMemberSelect':
      return field?.value?.map((value: any) =>
        formatMemberSelectValue(value, field?.componentProps?.tabs),
      )
    case 'EformDateRangePicker':
      return (field.componentProps?.ref?.current?.formateDate?.() || []).map((item, index) => {
        if (item) {
          if (index === 0) {
            return moment(item).format('YYYY-MM-DD HH:mm:ss');
          } else {
            const formatArr = (field?.componentProps?.format || '').split(/-|\s|\/|\:/);
            const date = moment(item);
            if (formatArr.length === 6) {
              return date.format('YYYY-MM-DD HH:mm:ss');
            } else {
              const toZero = (num) => num > 10 ? num : '0' + num
              return Array.from({length: 6}).reduce((pre,next, index) => {
                switch (index) {
                  case 0:
                    return date.year()
                  case 1:
                    return pre + '-' + (formatArr.length > 1 ? toZero(date.month() + 1) : 12)
                  case 2:
                    return pre + '-' + (formatArr.length > 2 ? toZero(date.date()) :  formatArr.length > 1 ? toZero(date.daysInMonth()) : 31)
                  case 3:
                    return pre + ' ' + (formatArr.length > 3 ? toZero(date.hour()) : 23)
                  case 4:
                    return pre + ':' + (formatArr.length > 4 ? toZero(date.minute()) : 59)
                  case 5:
                    return pre + ':' + (formatArr.length > 5 ? toZero(date.second()) : 59)
                }
              }, '')
            } 
          }
        }
      });
      
      return
    default:
      return field?.value
  }
}
const formatters = {
  formatOrders,
  getModels,
  getModelName,
  formatValue,
  getQueryGroups,
  filterCondition,
  formatFilterCondition,
  formatMemberSelectValue,
  removeHtmlTag,
  formatConditionValue
};




export default formatters;
